#ifndef _RING_QUEUE_HPP_
#define _RING_QUEUE_HPP_

#include <vector>
#include <semaphore.h>
#include <pthread.h>
using namespace std;

const int DEF_CAP = 5;

template <class T>
class RingQueue
{
    int _capacity;
    vector<T> _rq;
    int p_step; // 生产下标
    int c_step; // 消费下标
    sem_t _spaceSem;
    sem_t _dataSem;
    pthread_mutex_t _pmtx;
    pthread_mutex_t _cmtx;

public:
    RingQueue(int capacity = DEF_CAP)
        : _capacity(capacity),
          _rq(capacity),
          p_step(0),
          c_step(0)
    {
        sem_init(&_spaceSem, 0, capacity);
        sem_init(&_dataSem, 0, 0);
        pthread_mutex_init(&_pmtx, nullptr);
        pthread_mutex_init(&_cmtx, nullptr);
    }
    void push(const T &in)
    {
        // 先申请信号量
        sem_wait(&_spaceSem);
        // 再申请锁
        pthread_mutex_lock(&_pmtx);
        _rq[p_step++] = in;
        p_step %= _capacity;
        pthread_mutex_unlock(&_pmtx);
        sem_post(&_dataSem);
    }
    void pop(T *out)
    {
        // 先申请信号量
        sem_wait(&_dataSem);
        // 再申请锁
        pthread_mutex_lock(&_cmtx);
        *out = _rq[c_step++];
        c_step %= _capacity;
        pthread_mutex_unlock(&_cmtx);
        sem_post(&_spaceSem);
    }
    ~RingQueue()
    {
        sem_destroy(&_spaceSem);
        sem_destroy(&_dataSem);
        pthread_mutex_destroy(&_pmtx);
        pthread_mutex_destroy(&_cmtx);
    }
};

#endif